package com.smart.community.region.service.impl;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

import com.smart.community.commons.utils.StringUtils;
import com.smart.community.region.dto.RegionTreeVO;
import com.smart.community.region.entity.Region;
import com.smart.community.region.mapper.RegionMapper;
import com.smart.community.region.service.RegionCacheService;

import lombok.extern.slf4j.Slf4j;

/**
 * 区域缓存服务实现类
 * 
 * 功能说明：
 * 1. 为区域表的高频查询提供Caffeine内存缓存支持
 * 2. 使用@Cacheable注解实现自动缓存管理
 * 3. 解决BigDecimal序列化问题，支持复杂对象缓存
 * 4. 严格按照《Java后端SpringBoot代码开发规范_重构版.md》实现
 * 5. 遵循《智慧社区微服务架构总览.md》的Caffeine缓存设计规范
 * 
 * 缓存策略：
 * - 使用Caffeine本地内存缓存，无需序列化/反序列化
 * - 支持复杂对象（BigDecimal、RegionTreeVO等）直接缓存
 * - 通过@Cacheable注解自动管理缓存生命周期
 * - 缓存过期时间由CaffeineCacheConfig统一配置
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 2.0.0 - 迁移到Caffeine内存缓存
 */
@Slf4j
@Service
public class RegionCacheServiceImpl implements RegionCacheService {

    @Autowired
    private RegionMapper regionMapper;

    // ==================== 区域详情缓存 ====================

    @Override
    @Cacheable(value = "region:detail", key = "#regionId")
    public Region getRegionById(Long regionId) {
        log.debug("根据区域ID获取区域信息（Caffeine缓存），区域ID：{}", regionId);
        
        if (regionId == null) {
            log.warn("区域ID为空，返回null");
            return null;
        }
        
        return regionMapper.selectById(regionId);
    }

    @Override
    @Cacheable(value = "region:code", key = "#regionCode")
    public Region getRegionByCode(String regionCode) {
        log.debug("根据区域编码获取区域信息（Caffeine缓存），区域编码：{}", regionCode);
        
        if (StringUtils.isBlank(regionCode)) {
            log.warn("区域编码为空，返回null");
            return null;
        }
        
        return regionMapper.selectByRegionCode(regionCode);
    }

    @Override
    @Cacheable(value = "region:type", key = "#regionType")
    public List<Region> getRegionsByType(Integer regionType) {
        log.debug("根据区域类型获取区域列表（Caffeine缓存），区域类型：{}", regionType);
        
        if (regionType == null) {
            log.warn("区域类型为空，返回空列表");
            return Collections.emptyList();
        }
        
        List<Region> regions = regionMapper.selectByRegionType(regionType);
        return regions != null ? regions : Collections.emptyList();
    }

    @Override
    @Cacheable(value = "region:children", key = "#parentId != null ? #parentId : 'root'")
    public List<Region> getChildRegions(Long parentId) {
        log.debug("获取子区域列表（Caffeine缓存），父区域ID：{}", parentId);
        
        List<Region> regions = regionMapper.selectChildren(parentId);
        return regions != null ? regions : Collections.emptyList();
    }

    @Override
    @Cacheable(value = "region:path", key = "#regionId")
    public List<Region> getRegionPath(Long regionId) {
        log.debug("获取区域层级路径（Caffeine缓存），区域ID：{}", regionId);
        
        if (regionId == null) {
            log.warn("区域ID为空，返回空列表");
            return Collections.emptyList();
        }
        
        List<Region> regions = regionMapper.selectRegionPath(regionId);
        return regions != null ? regions : Collections.emptyList();
    }

    @Override
    @Cacheable(value = "region:tree", key = "#parentId != null ? #parentId : 'root'")
    public List<RegionTreeVO> getRegionTree(Long parentId) {
        log.debug("获取区域树形结构（Caffeine缓存），父区域ID：{}", parentId);
        
        List<RegionTreeVO> tree = regionMapper.selectRegionTree(parentId);
        return tree != null ? tree : Collections.emptyList();
    }

    @Override
    @Cacheable(value = "region:enabled", key = "'all'")
    public List<Region> getEnabledRegions() {
        log.debug("获取所有启用的区域列表（Caffeine缓存）");
        
        List<Region> regions = regionMapper.selectEnabledRegions();
        return regions != null ? regions : Collections.emptyList();
    }

    @Override
    @Cacheable(value = "region:all", key = "'all'")
    public List<Region> getAllRegions() {
        log.debug("获取所有区域列表（Caffeine缓存）");
        
        List<Region> regions = regionMapper.selectList(null);
        return regions != null ? regions : Collections.emptyList();
    }

    @Override
    @Cacheable(value = "region:parentIds", key = "#regionId")
    public List<Long> getAllParentRegionIds(Long regionId) {
        log.debug("获取所有父区域ID（Caffeine缓存），区域ID：{}", regionId);
        
        if (regionId == null) {
            log.warn("区域ID为空，返回空列表");
            return Collections.emptyList();
        }
        
        List<Long> parentIds = regionMapper.selectAllParentRegionIds(regionId);
        return parentIds != null ? parentIds : Collections.emptyList();
    }

    @Override
    @Cacheable(value = "region:childIds", key = "#regionId")
    public List<Long> getAllChildRegionIds(Long regionId) {
        log.debug("获取所有子区域ID（Caffeine缓存），区域ID：{}", regionId);
        
        if (regionId == null) {
            log.warn("区域ID为空，返回空列表");
            return Collections.emptyList();
        }
        
        List<Long> childIds = regionMapper.selectAllChildRegionIds(regionId);
        return childIds != null ? childIds : Collections.emptyList();
    }

    // ==================== 缓存管理 ====================

    @Override
    @CacheEvict(value = {"region:detail", "region:path", "region:children", "region:tree", "region:parentIds", "region:childIds", "region:enabled", "region:all"}, allEntries = true)
    public void clearRegionCache(Long regionId) {
        log.debug("清除区域缓存（Caffeine缓存），区域ID：{}", regionId);
        // Caffeine缓存通过@CacheEvict注解自动清理，无需手动操作
    }

    @Override
    @CacheEvict(value = "region:code", key = "#regionCode")
    public void clearRegionCodeCache(String regionCode) {
        log.debug("清除区域编码缓存（Caffeine缓存），区域编码：{}", regionCode);
        // Caffeine缓存通过@CacheEvict注解自动清理，无需手动操作
    }

    @Override
    @CacheEvict(value = "region:type", key = "#regionType")
    public void clearRegionTypeCache(Integer regionType) {
        log.debug("清除区域类型缓存（Caffeine缓存），区域类型：{}", regionType);
        // Caffeine缓存通过@CacheEvict注解自动清理，无需手动操作
    }

    @Override
    @CacheEvict(value = {"region:detail", "region:code", "region:type", "region:children", "region:path", "region:tree", "region:enabled", "region:all", "region:parentIds", "region:childIds"}, allEntries = true)
    public void clearAllRegionCache() {
        log.info("清除所有区域缓存（Caffeine缓存）");
        // Caffeine缓存通过@CacheEvict注解自动清理，无需手动操作
    }

    @Override
    public void warmUpRegionCache(List<Long> regionIds) {
        if (regionIds == null || regionIds.isEmpty()) {
            log.warn("区域ID列表为空，跳过缓存预热");
            return;
        }
        
        log.info("开始预热区域缓存（Caffeine缓存），区域ID数量：{}", regionIds.size());
        
        int successCount = 0;
        int failCount = 0;
        
        for (Long regionId : regionIds) {
            try {
                // 通过调用缓存方法实现预热
                Region region = getRegionById(regionId);
                if (region != null) {
                    successCount++;
                    log.debug("预热区域详情缓存成功，区域ID：{}", regionId);
                } else {
                    log.warn("区域不存在，跳过预热，区域ID：{}", regionId);
                }
            } catch (Exception e) {
                failCount++;
                log.warn("预热区域缓存失败，区域ID：{}", regionId, e);
            }
        }
        
        log.info("区域缓存预热完成，成功：{}，失败：{}", successCount, failCount);
    }

    @Override
    public void warmUpRegionTypeCache(List<Integer> regionTypes) {
        if (regionTypes == null || regionTypes.isEmpty()) {
            log.warn("区域类型列表为空，跳过缓存预热");
            return;
        }
        
        log.info("开始预热区域类型缓存（Caffeine缓存），区域类型数量：{}", regionTypes.size());
        
        int successCount = 0;
        int failCount = 0;
        
        for (Integer regionType : regionTypes) {
            try {
                // 通过调用缓存方法实现预热
                List<Region> regions = getRegionsByType(regionType);
                if (regions != null && !regions.isEmpty()) {
                    successCount++;
                    log.debug("预热区域类型缓存成功，区域类型：{}", regionType);
                } else {
                    log.warn("区域类型无数据，跳过预热，区域类型：{}", regionType);
                }
            } catch (Exception e) {
                failCount++;
                log.warn("预热区域类型缓存失败，区域类型：{}", regionType, e);
            }
        }
        
        log.info("区域类型缓存预热完成，成功：{}，失败：{}", successCount, failCount);
    }

    @Override
    public Object getCacheStatistics() {
        log.debug("获取Caffeine缓存统计信息");
        
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("cacheType", "Caffeine");
        statistics.put("description", "使用Caffeine本地内存缓存，无需序列化/反序列化");
        statistics.put("benefits", Arrays.asList(
            "支持复杂对象缓存（BigDecimal、RegionTreeVO等）",
            "无需序列化/反序列化，性能更高",
            "自动管理缓存生命周期",
            "解决Redis序列化问题"
        ));
        statistics.put("cacheNames", Arrays.asList(
            "region:detail", "region:code", "region:type", "region:children",
            "region:path", "region:tree", "region:enabled", "region:all",
            "region:parentIds", "region:childIds"
        ));
        statistics.put("timestamp", System.currentTimeMillis());
        
        return statistics;
    }

}
